﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Windows;
using System.Linq;
using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Presentation;
using OpenPowerPoint.Collection;
using OpenPowerPoint.Slides.Elements;
using Shape = OpenPowerPoint.Slides.Elements.Shape;
using System.Windows.Media;

namespace OpenPowerPoint.Slides
{
    /// <summary>
    /// Represents the basics of every slide type
    /// </summary>
    public class BaseSlide : DependencyObject, INotify
    {
        internal event NotifyableList<INotify>.PropertyChangedDelegate PropertyChanged;
        event NotifyableList<INotify>.PropertyChangedDelegate INotify.PropertyChanged
        {
            add { PropertyChanged += value; }
            remove { PropertyChanged -= value; }
        }

        bool _avoidPropertyChanged = false;
        internal virtual void OnPropertyChanged(object sender, SProperty property)
        {
            if (!_avoidPropertyChanged)
            {
                _avoidPropertyChanged = true;

                NotifyableList<INotify>.PropertyChangedDelegate handler = PropertyChanged;
                if (handler != null) handler(sender, property);

                if (property.Property != null)
                    SetValue(property.Property, property.NewValue);
                _avoidPropertyChanged = false;
            }
        }

        #region Load/Save

        /// <summary>
        /// Loads the shapes out of a CommonSlideData object
        /// </summary>
        /// <param name="commonSlideData">The content object to load from</param>
        protected void LoadCommonSlideData(CommonSlideData commonSlideData)
        {
            if (commonSlideData == null) return;
            if (commonSlideData.ShapeTree == null) return;

            List<DocumentFormat.OpenXml.Presentation.Shape> shapes =
                commonSlideData.ShapeTree.ChildElements.OfType<DocumentFormat.OpenXml.Presentation.Shape>().ToList();


            foreach (var shape in shapes)
                Shapes.Add(Shape.Load(shape));


            Title = commonSlideData.Name;
        }

        public static readonly DependencyProperty ShapesProperty =
            DependencyProperty.Register("Shapes", typeof(NotifyableList<Shape>), typeof(BaseSlide),
                                        new PropertyMetadata(default(NotifyableList<Shape>), (o, e) =>
                                                                                                 {
                                                                                                     if (e.NewValue != null)
                                                                                                         ((NotifyableList<Shape>)e.NewValue).PropertyChanged +=
                                                                                                             ((BaseSlide)o).OnPropertyChanged;
                                                                                                     if (e.OldValue != null)
                                                                                                         ((NotifyableList<Shape>)e.OldValue).PropertyChanged -=
                                                                                                             ((BaseSlide)o).OnPropertyChanged;
                                                                                                 }));

        public ObservableCollection<Shape> Shapes
        {
            get { return (ObservableCollection<Shape>)GetValue(ShapesProperty); }
            private set { SetValue(ShapesProperty, value); }
        }

        #endregion

        #region Initializer

        /// <summary>
        /// Initializes a new empty slide basis
        /// </summary>
        public BaseSlide()
        {
            Shapes = new NotifyableList<Shape>();
        }

        #endregion

        #region Functions
        /// <summary>
        /// Updates the color in all shapes
        /// </summary>
        /// <param name="old">The color to update</param>
        /// <param name="update">The new color</param>
        protected void UpdateColor(Color old, Color update)
        {
            foreach (var shape in Shapes)
            {
                shape.UpdateColor(old, update);
            }
        }
        #endregion

        #region Properties
        public static readonly DependencyProperty TitleProperty = DependencyProperty.Register("Title", typeof(string), typeof(SlideLayout), new PropertyMetadata(""));

        /// <summary>
        /// Gets or sets the identifier for this slide
        /// </summary>
        public string Title
        {
            get { return (string)GetValue(TitleProperty); }
            set { SetValue(TitleProperty, value); }
        }
        #endregion
    }
}
